﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InnovTech.Util.Workflow
{
    public class Workflow
    {

        public Workflow()
        {
            Steps = new Dictionary<int, WorkflowStepBase>();
        }

        public Workflow(IEnumerable<WorkflowStepBase> steps)
            : base()
        {
            Add(steps);
        }

        public Dictionary<int, WorkflowStepBase> Steps { get; private set; }

        public void Execute()
        {
            IEnumerable<int> orderedIndex = Steps.Keys.OrderBy( index => index);
            foreach (var idx in orderedIndex)
            {
                Steps[idx].Run();
            }
        }

        public void Add(WorkflowStepBase step)
        {
            Add(Steps.Keys.Max() + 1, step);
        }

        public void Add(int index, WorkflowStepBase step)
        {
            if (step == null) return;
            if (Steps.Keys.Contains(index))
                throw new ArgumentException("The given index exists already.");
            Steps.Add(index, step);
        }

        public void Add(Dictionary<int, WorkflowStepBase> steps)
        {
            if (steps == null) return;
            foreach (var step in steps)
                Add(step.Key, step.Value);
        }

        public void Add(IEnumerable<WorkflowStepBase> steps)
        {
            if (steps != null)
            {
                int currentIndex = Steps.Keys.Max() + 1;
                foreach (var step in steps)
                {
                    Add(currentIndex++, step);
                }
            }
        }

        public void Add(Action stepAct, EventHandler started, EventHandler finished, int index = -1)
        {
            if(stepAct == null)
                throw new ArgumentNullException("The given step can not be null.");

            WorkflowStep step = new WorkflowStep(stepAct, started, finished);
            if (index == -1)
                Add(step);
            else
                Add(index, step);
        }
    }


}
